;; Starter file for CS1102 lab 6 on state and web programming
;; Charles Rich (adapted from Kathi Fisler), WPI
(require racket/list)

(load "server.rkt") ;file must be in same folder

;; Note: Much advisable error checking is omitted here in order
;; not to clutter the code, so that the main pedagogical points
;; are more evident -CR

;;;;;;; DATA DEFINITIONS ;;;;;;;;;;;;;;;;;;;;;;;;

;; a hotel is (make-hotel symbol string)
(define-struct hotel (name descr))

(define HOTEL-DATA
  (list (make-hotel 'Motel6 "Wastes electricity by leaving lights on")
        (make-hotel 'Hilton "We'll always have Paris")
        (make-hotel 'DaysInn "Great for nights out")))

;;;;;;;;; VERSION 1 - NON-WEB MOCKUP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define (hotel-main-page)
  (printf "Welcome! Which hotel do you want to view?~n")
  (print-choices HOTEL-DATA)
  (let ([chosen-hotel (list-ref HOTEL-DATA (read))])
    (printf "Details for ~a: ~a~n~n"
            (hotel-name chosen-hotel) 
            (hotel-descr chosen-hotel))
    (printf "Enter the day of this month you want to reserve or no to skip this hotel: ~n~n")
    (let ([reserve-for (read)])
      (cond [(number? reserve-for) 
             (printf "Congrats, you have a reservation at the ~a for day ~a of this month!~n" 
                     (hotel-name chosen-hotel) reserve-for)]
            [(eq? reserve-for 'no) (hotel-main-page)]))))

;; print-choices : list[hotel] -> void
;; numbers hotel names and prints them out
(define (print-choices data)
  (for-each (lambda (numstr ahotel) 
              (printf "  ~a: ~a~n" numstr (hotel-name ahotel)))
            (build-list (length data) number->string)
            data))

;;;;;;;;; VERSION 2 - WEB VERSION WITH COOKIE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Note: 
;;   - assuming using local port 8088
;;   - following Version 1 as closely as possible in order to highlight
;;     comparison, rather than using fancy html (such as radio buttons)

(define (current-reservations cookies)
  (let ([val (get-cookie/single "cs1102-reservations" cookies)])
    (cond [(boolean? val) ""]
          [else val])))

(define-script (hotel-main-page form cookies) ;args ignored
  (values 
   (html-page "Hotel Main Page"
              "Welcome! Which hotel do you want to view?"
              (append '(form ([action "http://localhost:8088/reserve"]
                              [target "_blank"])) ;in new window/tab
                      (format-choices HOTEL-DATA)
                      '((input ([type "text"] [name "choice"]))))
              '(br)
              (append (list 'pre
                 "Current reservations: ")
                (get-cookie "cs1102-reservations"  cookies))
              )
   ;; no cookie
   false))

(define-script (reserve form cookies)
  (let* ([chosen-hotel (list-ref HOTEL-DATA (string->number (cdr (assoc 'choice form))))]
         [chosen-hotel-name (symbol->string (hotel-name chosen-hotel))])
    (values
     (html-page chosen-hotel-name
                (format "Details for ~a: ~a" 
                        chosen-hotel-name (hotel-descr chosen-hotel)) 
                '(br) 
                '(br)
                "Enter the day of this month you want to reserve or no to skip this hotel:"
                (list 'form '([action "http://localhost:8088/confirm"])
                       '(input ([type "text"] [name "day"]))
                       (list 'input (list '[type "hidden"] '[name "hotel"] [list 'value chosen-hotel-name]))))
     ;; send cookie
     (set-cookie "cs1102-hotel-choice" chosen-hotel-name))))

(define-script (confirm form cookies)
  (let* ([reserve-for (cdr (assoc 'day form))]
         [reserve-name (cdr (assoc 'hotel form))]
         )
    (cond [(string->number reserve-for)
           (values
            (html-page "Confirmation"
                       (format "Congrats, you have a reservation at the ~a for day ~a of this month!" 
                               reserve-name
                               reserve-for))
            ;; no cookie
            (set-cookie 
             "cs1102-reservations" 
             (string-append 
              "Reservation for hotel " 
              reserve-name
              " for "
              reserve-for
              " days")))]
          [(string=? reserve-for "no")
           (invoke "hotel-main-page" form cookies)])))

;; format-choices : list[hotel] -> list[string]
;; produces numbered list of hotel names
(define (format-choices data)
  (append-map (lambda (numstr ahotel) 
                (list (format "  ~a: ~a" numstr (hotel-name ahotel)) '(br)))
              (build-list (length data) number->string)
              data))

